package com.wanlian.router.net;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextThemeWrapper;

import com.google.gson.Gson;
import com.wanlian.router.event.LogOut;
import com.wanlian.router.net.internal.BaseHttpClient;
import com.wanlian.router.net.internal.DefaultParser;
import com.wanlian.router.net.internal.INetCallBack;
import com.wanlian.router.net.internal.IParser;
import com.wanlian.router.net.internal.Platform;
import com.wanlian.router.net.internal.ResponseHandleInterface;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Response;

/**
 * Created by Hyu on 2016/7/11.
 * Email: fvaryu@qq.com
 */
public abstract class AsyncHttpResponseHandler implements ResponseHandleInterface {

    private Context mContext;
    private ParserResult mParserResult = new ParserResult();
    private boolean isShow;
    private IParser mIParser;
    private INetCallBack mCallBack;
    private Object tag;
    private Platform mPlatform;
    private Gson mGson;
    private boolean printLog;

    private BaseHttpClient mBaseHttpClient;
    private ProgressDialog mLoadingDialog;

    public AsyncHttpResponseHandler(Context context, BaseHttpClient client, Platform platform,
                                    boolean printLog,
                                    boolean isShow, Object tag,
                                    IParser iParser, Gson gson,
                                    INetCallBack callBack) {
        this.mContext = context;
        this.mBaseHttpClient = client;
        this.printLog = printLog;
        this.mIParser = iParser;
        this.mCallBack = callBack;
        this.tag = tag;
        this.mPlatform = platform;
        this.isShow = isShow && platform != null;
        this.mGson = gson;
        if (mGson == null) {
            this.mGson = new Gson();
        }
    }

    public Context getContext() {
        return mContext;
    }

    public Object getTag() {
        return tag;
    }

    public boolean isShow() {
        return isShow;
    }

    public void setShow(boolean show) {
        isShow = show;
    }


    public BaseHttpClient getHttpClient() {
        return mBaseHttpClient;
    }


        @Override
    public void onStart() {
        if (!isShow) return;

        mLoadingDialog = new ProgressDialog(mContext);
        mLoadingDialog.setCanceledOnTouchOutside(false);
        mLoadingDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {
                /**
                 * 如果是网络请求完成，dialog消失不在去调用取消请求 isShow = false
                 * 如果是用户点击back/屏幕，要请求cancel request， isShow = true
                 * {@link AsyncHttpResponseHandler#dismiss()}
                 */
                if (!isShow) {
                    return;
                }
                NetWorkingClient.getInstance().cancelByTag(tag);
            }
        });
        mLoadingDialog.show();
    }
//
//
    private void dismiss() {
        if (!isShow || mLoadingDialog == null) {
            return;
        }
        isShow = false;
        mLoadingDialog.dismiss();
    }

    private boolean isActivityRunning(Context context) {
        if (context instanceof Activity) {
            return ((Activity) context).isFinishing() || ((Activity) context).isDestroyed();
        }
        return false;
    }

    private boolean isWindowFinish() {
        if (mContext == null) {
            return true;
        }

        if (mContext instanceof Activity) {
            return isActivityRunning(mContext);
        }
        if (mContext instanceof ContextThemeWrapper) {
            Context context = ((ContextThemeWrapper) mContext).getBaseContext();
            return isActivityRunning(context);
        }
        return true;
    }

    @Override
    public void onFailure(Call call, IOException e) {
        if (call.isCanceled()) {
            if (printLog)
                Log.i(BaseHttpClient.TAG, "Http is Canceled ,but fail response back, not deal");
            return;
        }
        if (isWindowFinish()) {
            if (printLog)
                Log.i(BaseHttpClient.TAG, "http response, window destroy");
            return;
        }
        if (printLog) {
            Log.i(BaseHttpClient.TAG, String.format("request data:\n%s", call.request().url()));
            Log.i(BaseHttpClient.TAG, e.getMessage());
        }
        mParserResult.res = new ResponseData();
        finished();
    }

    @Override
    public void onResponse(Call call, final Response response) throws IOException {
        if (call.isCanceled()) {
            if (printLog)
                Log.i(BaseHttpClient.TAG, "Http is Canceled ,but response back, not deal");
            return;
        }
        if (isWindowFinish()) {
            if (printLog)
                Log.i(BaseHttpClient.TAG, "http response, window destroy");
            return;
        }
        if (printLog)
            Log.i(BaseHttpClient.TAG, String.format("request data:\n%s", call.request().url()));
        if (response.isSuccessful()) {
            String resData = response.body().string();
            if (printLog)
                Log.i(BaseHttpClient.TAG, String.format("response data:\n%s", resData));
            if (!TextUtils.isEmpty(resData)) {
               ResponseData res = new DefaultParser().parser(mGson, response.code(), response.headers(), resData);
                mParserResult.res = res;
                if (mIParser != null && !(mIParser instanceof DefaultParser) && res.isSuccess()) {
                    mParserResult.mT = mIParser.parser(mGson, response.code(), response.headers(), resData);
                }
            }
            finished();
        } else {
            onFailure(call, new IOException("http is fail, code=" + response.code() + " ,message=" + response.message()));
        }
    }

    @SuppressWarnings("unchecked")
    private void finished() {

        if (mPlatform == null) {
            fire();
        } else {
            mPlatform.execute(new Runnable() {

                @Override
                public void run() {
                    fire();
                    onStop();
                }
            });
        }
    }

    private void fire() {
        if (mCallBack != null) {
            if (mParserResult.res == null) {
                mParserResult.res = new ResponseData();
            }

            if (isWindowFinish()) {
                return;
            }

            mCallBack.onFinish(mParserResult.res, mParserResult.mT);
            dismiss();

            if (mParserResult.res.getErrorTag() == 10001) {
                EventBus.getDefault().post(new LogOut());
            }

        }
    }


    private class ParserResult<T> {
        public ResponseData res = null;
        public T mT;
    }
}
